#include "Renderer.h"
#include "VertexBuffer.h"
#include "Structs.h"
// interface de directx
LPDIRECT3D9       g_pDirect3D = NULL;


Renderer::Renderer(HWND hWnd)://constructor
m_hWnd(hWnd), m_pkDevice(NULL),
m_kViewerPos(0.0f, 0.0f, -5.0f),
m_kViewerUp(0.0f, 1.0f, 0.0f),
m_fViewerAngle(0.0f)//init variables
{
	D3D_Initialize(hWnd);//llamo a init d3d que inicializa directx
	m_pkVertexBuffer.Create(m_pkDevice,true);


}


Renderer::~Renderer(void)
{
	m_pkDevice->Release();
	g_pDirect3D->Release();
}

void Renderer::D3D_Initialize(HWND hWnd)
{
	//----------------------------------------------------------
	// Inicializar DX
	// creo la interface de d3d
	g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);


	D3DPRESENT_PARAMETERS PresentParams;
	ZeroMemory(&PresentParams, sizeof(PresentParams));//pongo en null todo.
	PresentParams.Windowed = TRUE; // es modo ventana
	PresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;// no guarda los anteriores back buffers.(mas rapido pero no podes hacer algunos efectos)
	
	//Creo el device de dx
	HRESULT hr = g_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT,
								D3DDEVTYPE_HAL,
								hWnd,
								D3DCREATE_SOFTWARE_VERTEXPROCESSING,
								&PresentParams,
								&m_pkDevice);
	setViewportPosition(0,0);
	D3DVIEWPORT9 kViewport;
	m_pkDevice->GetViewport(&kViewport);
	
	D3DXMatrixOrthoLH(&m_mProjectionMatrix,(float) kViewport.Width, (float) kViewport.Height, -25,25);

	if(!m_pkVertexBuffer.Create(m_pkDevice, true))
		return;
}
void Renderer::setViewportPosition(float fPosX,float fPosY)
{
	m_kViewerPos.x = fPosX;
	m_kViewerPos.y = fPosY;
	m_kViewerPos.z = -5.0f;
	
	D3DXMATRIX kMatrix;
	D3DXVECTOR3 kLookPos;

	kLookPos.x = m_kViewerPos.x;	
	kLookPos.y = m_kViewerPos.y;
	kLookPos.z = 0.0f;

	D3DXMatrixLookAtLH(&kMatrix, &m_kViewerPos, &kLookPos, &m_kViewerUp);
	m_pkDevice->SetTransform(D3DTS_VIEW, &kMatrix);
}
void Renderer::StartFrame(){
	//limpio el device
	m_pkDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255),

                          1.0f, 0);
	//preparo la ecena
	m_pkDevice->BeginScene();
}
void Renderer::EndFrame(){
	
	//termino la ecena
	m_pkDevice->EndScene();
	//muestro la ecena creada en el frame
	m_pkDevice->Present(NULL, NULL, NULL, NULL);
}
void Renderer::Draw(ColorVertex * pVtxCollection, D3DPRIMITIVETYPE primitiveType, unsigned int uiVtxCount)
{
	StartFrame();
	m_pkVertexBuffer.Bind();
	m_pkVertexBuffer.Draw(pVtxCollection,primitiveType,uiVtxCount);
	
//	m_pkVertexBuffer.Flush();
	EndFrame();
}
void Renderer::setMatrixMode (MatrixMode eMode)
{
	m_eCurrentMatMode = eMode;
}
//----------------------------------------------------------------
void Renderer::loadIdentity ()
{
	D3DXMATRIX kTempMatrix;

	// set identity matrix
	D3DXMatrixIdentity(&kTempMatrix);

	// if it is a view matrix, use default values
	if (m_eCurrentMatMode == VIEW) {
		
		D3DXVECTOR3 kEyePos(0,0,-1);
		D3DXVECTOR3 kLookPos(0,0,0);
		D3DXVECTOR3 kUpVector(0,1,0);
		
		// generate the view matrix
		D3DXMatrixLookAtLH(&kTempMatrix, &kEyePos, &kLookPos, &kUpVector);
	}
	
	// convert from MatrixMode to D3DTRANSFORMSTATETYPE
	D3DTRANSFORMSTATETYPE eMatMode = static_cast<D3DTRANSFORMSTATETYPE>(m_eCurrentMatMode);
	
	// set the matrix
	m_pkDevice->SetTransform(eMatMode, &kTempMatrix);
}
void Renderer::translate (float fX, float fY, float fZ)
{
	D3DXMATRIX kTempMatrix;	

	// generate translation matrix
	D3DXMatrixTranslation(&kTempMatrix, fX,  fY, fZ);

	// convert from MatrixMode to D3DTRANSFORMSTATETYPE
	D3DTRANSFORMSTATETYPE eMatMode = static_cast<D3DTRANSFORMSTATETYPE>(m_eCurrentMatMode);

	// set the matrix
	m_pkDevice->MultiplyTransform(eMatMode, &kTempMatrix);
}
//----------------------------------------------------------------
void Renderer::rotateX (float fAngle)
{
	D3DXMATRIX kTempMatrix;

	// generate translation matrix
	D3DXMatrixRotationX(&kTempMatrix, fAngle);

	// convert from MatrixMode to D3DTRANSFORMSTATETYPE
	D3DTRANSFORMSTATETYPE eMatMode = static_cast<D3DTRANSFORMSTATETYPE>(m_eCurrentMatMode);

	// set the matrix
	m_pkDevice->MultiplyTransform(eMatMode, &kTempMatrix);
}
//----------------------------------------------------------------
void Renderer::rotateY (float fAngle)
{
	D3DXMATRIX kTempMatrix;

	// generate translation matrix
	D3DXMatrixRotationY(&kTempMatrix, fAngle);

	// convert from MatrixMode to D3DTRANSFORMSTATETYPE
	D3DTRANSFORMSTATETYPE eMatMode = static_cast<D3DTRANSFORMSTATETYPE>(m_eCurrentMatMode);

	// set the matrix
	m_pkDevice->MultiplyTransform(eMatMode, &kTempMatrix);
}
//----------------------------------------------------------------
void Renderer::rotateZ (float fAngle)
{
	D3DXMATRIX kTempMatrix;

	// generate translation matrix
	D3DXMatrixRotationZ(&kTempMatrix, fAngle);

	// convert from MatrixMode to D3DTRANSFORMSTATETYPE
	D3DTRANSFORMSTATETYPE eMatMode = static_cast<D3DTRANSFORMSTATETYPE>(m_eCurrentMatMode);

	// set the matrix
	m_pkDevice->MultiplyTransform(eMatMode, &kTempMatrix);
}
//----------------------------------------------------------------
void Renderer::scale (float fW, float fH)
{
	D3DXMATRIX kTempMatrix;

	// generate scale matrix
	D3DXMatrixScaling(&kTempMatrix, fW,  fH, 1.0f);

	// convert from MatrixMode to D3DTRANSFORMSTATETYPE
	D3DTRANSFORMSTATETYPE eMatMode = static_cast<D3DTRANSFORMSTATETYPE>(m_eCurrentMatMode);

	// set the matrix
	m_pkDevice->MultiplyTransform(eMatMode, &kTempMatrix);
}